#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   conftest.py
@Time    :   2022/02/23 09:16:36
@Author  :   WangWei 
@Version :   1.0
@Contact :   wangwei@chengtech.com
@License :   (C)Copyright 2022-2025
@Desc    :   None
'''
import shutil
import sys
import os
import logging
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.abspath(os.path.dirname(curPath) + os.path.sep + ".")
sys.path.append(rootPath)
sys.path.append(os.path.join(curPath,'commDriver'))
sys.path.append(os.path.join(curPath,'data'))
logging.info(sys.path)


# here put the import lib
import pytest
import sys
import os
import time
import datetime
import allure
from py._xmlgen import html
import traceback

# from commDriver.CAN import *
from commDriver.TS_CAN import *
from commDriver.power import *
from project_CAN import *
import project_CAN

import Set_up

__Driver = {}

sys.dont_write_bytecode = True


# 这里我设置的级别是模块级别，也就是每个测试文件运行一次
# 可以设置为session，全部用例执行一次
@pytest.fixture(scope='session')
def Driver():
    global __Driver

    # Init CAN Tool
    try:
        logging.info("open CAN_Driver".center(50, '-'))

        project_rbs = real_CAN(Set_up.drive_type,Set_up.configure_baudrate)
        project_rbs2 = real_CAN(Set_up.drive_type,Set_up.configure_baudrate2,TSMasterAPI.CHANNEL_INDEX.CHN2)
        project_rbs.load_dbc(Set_up.project_DBC_File_CAN)

        project_rbs.register_event_canfd_T_pre(OnCANPreFDevent)
        project_rbs.register_event_canfd_T_R(OnCANPreFDevent_checkPCAN)
        project_rbs.connect_application()
        project_rbs.RBS_Config(Set_up.NetName,Set_up.EnableNode)

        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'EPS_0x11F', 'Failure_Stats_OK_S', 1)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'EPS_0x11F', 'Sensor_Calibration_Stats_S', 1)

        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x223', 'IPB_AX_Status_S', 1)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x223', 'IPB_AY_Status_S', 1)

        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x220', 'RR_Wheel_Drive_Direction_S', 1)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x220', 'RL_Wheel_Drive_Direction_S', 1)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x220', 'FR_Wheel_Drive_Direction_S', 1)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x220', 'FL_Wheel_Drive_Direction_S', 1)

        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x220', 'RR_Wheel_Drive_Direct_Stat_S', 0)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x220', 'RL_Wheel_Drive_Direct_Stat_S', 0)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x220', 'FR_Wheel_Drive_Direct_Stat_S', 0)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x220', 'FL_Wheel_Drive_Direct_Stat_S', 0)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x3D9', 'Valid_Mileage_S', 0)
        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x3D9', 'Total_Distance_3D9s5_S', 10)

        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'IPB_0x222', 'Yaw_Rate_Status_S', 1)

        project_rbs.write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x12D', 'BCMPower_Gear_12D_S', 3)

        # logging.info("采用故障注入，清除故障".center(30, '*'))
        # project_rbs2.sendAndread_CMD_Shell(0x114,'profile 0',20)

        # project_rbs2.sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNeverDone_Enable 0 C 1 1',20)
        # project_rbs2.sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNeverDone_val 0 s 1 0',20)

        # project_rbs2.sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNotDone_Enable 0 C 1 1',20)
        # project_rbs2.sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNotDone_val 0 s 1 0',20)

        # project_rbs2.sendAndread_CMD_Shell(0x114,'cmd set gExInj_VariantCodeDet_Enable 0 C 1 1',20)
        # project_rbs2.sendAndread_CMD_Shell(0x114,'cmd set gExInj_VariantCodeDet_val 0 s 1 0',20)

        project_rbs.set_0x121_rolling_counter_error(enable=False)
        project_rbs.set_0x121_checksum_error(enable=False)

        project_rbs.set_0x11F_rolling_counter_error(enable=False)
        project_rbs.set_0x11F_checksum_error(enable=False)

        # project_rbs.set_0x294_rolling_counter_error(enable=False)
        # project_rbs.set_0x294_checksum_error(enable=False)

        project_rbs.set_0x240_rolling_counter_error(enable=False)
        project_rbs.set_0x240_checksum_error(enable=False)

        project_rbs.set_0x242_rolling_counter_error(enable=False)
        project_rbs.set_0x242_checksum_error(enable=False)

        project_rbs.set_0x341_rolling_counter_error(enable=False)
        project_rbs.set_0x341_checksum_error(enable=False)

        project_rbs.set_0x342_rolling_counter_error(enable=False)
        project_rbs.set_0x342_checksum_error(enable=False)

        project_rbs.set_0x123_rolling_counter_error(enable=False)
        project_rbs.set_0x123_checksum_error(enable=False)

        project_rbs.set_0x1F0_rolling_counter_error(enable=False)
        project_rbs.set_0x1F0_checksum_error(enable=False)

        project_rbs.set_0x220_rolling_counter_error(enable=False)
        project_rbs.set_0x220_checksum_error(enable=False)

        project_rbs.set_0x222_rolling_counter_error(enable=False)
        project_rbs.set_0x222_checksum_error(enable=False)

        project_rbs.set_0x223_rolling_counter_error(enable=False)
        project_rbs.set_0x223_checksum_error(enable=False)

        project_rbs.set_0x321_rolling_counter_error(enable=False)
        project_rbs.set_0x321_checksum_error(enable=False)

        project_rbs.set_0x422_rolling_counter_error(enable=False)
        project_rbs.set_0x422_checksum_error(enable=False)

        project_rbs.set_0x1FC_rolling_counter_error(enable=False)
        project_rbs.set_0x1FC_checksum_error(enable=False)

        project_rbs.set_0x24C_rolling_counter_error(enable=False)
        project_rbs.set_0x24C_checksum_error(enable=False)

        project_rbs.set_0x11F_rolling_counter_error(enable=False)
        project_rbs.set_0x11F_checksum_error(enable=False)

        project_rbs.set_0x12D_rolling_counter_error(enable=False)
        project_rbs.set_0x12D_checksum_error(enable=False)

        project_rbs.set_0x3D9_rolling_counter_error(enable=False)
        project_rbs.set_0x3D9_checksum_error(enable=False)

        project_rbs.set_0x134_rolling_counter_error(enable=False)
        project_rbs.set_0x134_checksum_error(enable=False)

        project_rbs.set_0x195_rolling_counter_error(enable=False)
        project_rbs.set_0x195_checksum_error(enable=False)

        project_rbs.set_0x1A7_rolling_counter_error(enable=False)
        project_rbs.set_0x1A7_checksum_error(enable=False)

        project_rbs.set_0x109_rolling_counter_error(enable=False)
        project_rbs.set_0x109_checksum_error(enable=False)

        project_rbs.set_0x258_rolling_counter_error(enable=False)
        project_rbs.set_0x258_checksum_error(enable=False)

        project_rbs.set_0x2F6_rolling_counter_error(enable=False)
        project_rbs.Enable_0x2F6_CRC_Error(enable=False)

        __Driver['CAN'] = project_rbs
        logging.info("open CAN_Driver success".center(50, '-'))
        __Driver['CAN2'] = project_rbs2
        logging.info("open CAN_Driver2 success".center(50, '-'))

        # __Driver['PLC'] = Modbus
        # logging.info("open CAN_Driver2 success".center(50, '-'))

        
    except Exception as e:
        logging.info(traceback.print_exc())
        __Driver['CAN'].app.disconnect()
        logging.info("open CAN_Driver failed".center(50, '-'))
        

    # Init UDS support
    try:
        if Set_up.CAN_Type == 'CAN':
            SupportFD = 0
            Maxdlc = 8
        else:
            SupportFD = 1
            Maxdlc = 16

        diag = TSCAN_UDS(ASupportFD=SupportFD, AMaxdlc=Maxdlc, reqID=Set_up.reqID,resID=Set_up.resID,AFctID=Set_up.AFctID)
        diag2 = TSCAN_UDS(ChannelIndex=TSMasterAPI.CHANNEL_INDEX.CHN2, ASupportFD=1, AMaxdlc=15, reqID=Set_up.reqID,resID=Set_up.resID,AFctID=Set_up.AFctID)
        __Driver['UDS'] = diag
        __Driver['UDS2'] = diag2
        # diag.req_and_res_can([0x22,0xf1,0x90],3)
        # diag.UDS_can_delete()
        logging.info("Creat UDS_Handle successful".center(50, '-'))
        pass
    except Exception as e:
        logging.info("Creat UDS_Handle failed ".center(50, '-'))
        pass


    # Init Power supply
    try:
        logging.info("open power_Driver".center(50, '-'))
        project_power = power(source=Set_up.source,baudrate=Set_up.baudrate)
        project_power.config()
        project_power.Enable(True)
        v,i =project_power.Read_Measure()
        project_power.set_vltage(14)
        __Driver['power'] = project_power
        time.sleep(1)
        logging.info("open power_Driver success".center(50, '-'))
    except Exception as e:
        logging.info(traceback.print_exc())
        try:
            __Driver['power'].close()
        except Exception as e: 
            pass  
        logging.info("open power_Driver failed ".center(50, '-'))

    yield __Driver

    __Driver['CAN'].dis_connect_application()
    logging.info("close CAN_Driver".center(50, '-'))

    __Driver['UDS'].UDS_can_delete()
    __Driver['UDS2'].UDS_can_delete()
    

    try:
        __Driver['power'].close
    except Exception as e: 
        pass  
    logging.info("close power_Driver".center(50, '-'))

    # _CAN_driver.send(1,0x101,[1,2,3,4,15,16,17,18])
    # msg = _CAN_driver.receive(0)
    # for m in msg:
    #     logging.info('ID {:x}'.format(m.ID))
    #     logging.info(*(m.Data))

@pytest.fixture()
def action():
    blfname = datetime.datetime.now().strftime('%Y-%m-%d_%H_%M_%S') + '.blf'
    project_BLF_File_CAN = os.path.join(Set_up.root, f"blf\{blfname}")
    __Driver['CAN'].tsapp_start_logging(project_BLF_File_CAN)
    logging.info("测试用例开始".center(30, '*'))
    time.sleep(1)
    yield
    time.sleep(0.5)
    real_CAN.Reset_Setup_Pcanlist(True) 
    time.sleep(0.5)
    __Driver['UDS'].req_and_res_can([0x10,0x01],2)
    __Driver['CAN'].tsapp_stop_logging()
    logging.info("测试用例结束".center(30, '*'))
    
@pytest.fixture()
def BCMPower_Gear():
    __Driver['CAN'].write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x12D', 'BCMPower_Gear_12D_S', 3)
    __Driver['CAN'].write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x3D9', 'Total_Distance_3D9s5_S', 10)
    logging.info("设置BCMPower_Gear_12D_S为ON档,并等待3s".center(30, '*'))
    time.sleep(3)
    yield
    __Driver['CAN'].write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x12D', 'BCMPower_Gear_12D_S', 1)
    __Driver['CAN'].write_db_signal('Vehicle_CAN', 'BCM', 'Left_BCM_0x3D9', 'Total_Distance_3D9s5_S', 10)
    logging.info("设置BCMPower_Gear_12D_S为OFF档,并等待0.5s".center(30, '*'))
    time.sleep(0.8)


@pytest.fixture()
def Fault_Injection():
    logging.info("采用故障注入，清除故障".center(30, '*'))
    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'profile 0',20)

    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNeverDone_Enable 0 C 1 1',20)
    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNeverDone_val 0 s 1 0',20)

    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNotDone_Enable 0 C 1 1',20)
    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_AlignmentNotDone_val 0 s 1 0',20)

    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_VariantCodeDet_Enable 0 C 1 1',20)
    __Driver['CAN2'].sendAndread_CMD_Shell(0x114,'cmd set gExInj_VariantCodeDet_val 0 s 1 0',20)
    time.sleep(3)
    yield
    time.sleep(0.5)

@pytest.fixture()
def power_reset():
    real_CAN.Reset_Setup_Pcanlist(True) 
    __Driver['power'].Enable(False)
    time.sleep(1)
    __Driver['power'].Enable(True)
    time.sleep(3)

@pytest.fixture(scope='function',autouse=False)
def default_session():
    time.sleep(2)
    with allure.step('Step1:Request [0x10,0x01]'):
        __Driver['UDS'].req_and_res_can([0x10,0x01],2)

@pytest.fixture(scope='function',autouse=False)
def extend_session():
    time.sleep(2)
    with allure.step('Step1:Request [0x10,0x03]'):
        __Driver['UDS'].req_and_res_can([0x10,0x03],2)

@pytest.fixture(scope='function',autouse=False)
def programming_session():
    time.sleep(2)
    with allure.step('Step1:Request [0x10,0x03]'):
        __Driver['UDS'].req_and_res_can([0x10,0x03],2)
    time.sleep(0.1)
    __Driver['CAN'].unlock(__Driver,2)
    with allure.step('Step4:Request [0x10,0x02]'):
        __Driver['UDS'].req_and_res_can([0x10,0x02],2)
    time.sleep(2)
    yield
    __Driver['UDS'].req_and_res_can([0x10,0x01],2)


# @pytest.fixture(scope=“class”,autouse=True)
@pytest.fixture(scope='module',autouse=True)
def power_reset_for_class():
    real_CAN.Reset_Setup_Pcanlist(True) 
    __Driver['power'].Enable(False)
    logging.info('power reset for module')
    time.sleep(1)
    __Driver['power'].Enable(True)
    __Driver['power'].set_vltage(14)
    time.sleep(4)

def pytest_configure(config):

    pss = { '01 16 09 06 00':'美信',
            '0b 17 09 0d 00':'MPC_70331',
            '03 16 0c 1f 00':'MPC_70331',
            '05 16 0c 1f 00':'MPC_4323',
            '06 16 0c 1f 00':'MPC_9840',
            '0b 17 0a 08 00':'MPC_70331_230Pro',
            '0c 18 03 05 00':'MPC_70331_220Pro_j',
            }

    PowerSupplySolution = pss[Set_up.ECUHardwareVersionNumber]

    # Add interface address and project info
    #TODO, below info import from common folder Comm_Config.py file
    config._metadata["Software version"] = Set_up.Dut_Type + ' - V' + Set_up.APP_ver[0] + '.' + Set_up.APP_ver[1:3]+ '.' + Set_up.APP_ver[3:5]
    config._metadata["boot version"] = Set_up.bootver
    config._metadata["Build tag"] = "XX.XX.XX.XX"
    config._metadata["SN"] = "BYD 0.0.0.1"
    config._metadata["Power supply solution"] = PowerSupplySolution
    config._metadata["Test time"] = datetime.date.today()

    # Delete Java_Home
    config._metadata.pop("Python")
    config._metadata.pop("Plugins")
    config._metadata.pop("Packages")

    if os.path.exists('../Radar_report.html') and os.path.getsize('../Radar_report.html') > 16000:
        '''拷贝allure-results'''
        source_path = "../allure-results"
        target_path = "../" + PowerSupplySolution + datetime.datetime.now().strftime("_%y%m%d%H%M")
        allure_target_path = target_path + "/allure-results"
        if not os.path.exists(target_path):
            # 如果目标路径不存在原文件夹的话就创建
            os.makedirs(allure_target_path)
        if os.path.exists(source_path):
            # 如果目标路径存在原文件夹的话就先删除
            shutil.rmtree(allure_target_path)
        time.sleep(1)
        shutil.move(source_path, allure_target_path)

        '''拷贝Radar_report'''
        source_path = "../Radar_report.html"
        html_target_path = target_path + "/"
        time.sleep(1)
        shutil.move(source_path, html_target_path)


@pytest.mark.optionalhook
def pytest_html_results_summary(prefix, summary, postfix):
    prefix.extend([html.p("Tester: YangLiang")])
    prefix.extend([html.p("Report version: 0.0.1")])


@pytest.mark.optionalhook
def pytest_html_results_table_header(cells):
    cells.pop()

@pytest.mark.optionalhook
def pytest_html_results_table_row(report, cells):
    cells.pop()

@pytest.mark.hookwrapper
def pytest_runtest_makereport(item, call):
    outcome = yield
    report = outcome.get_result()
